package com.lifp.thread.lock;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 多线程加减法测试
 *
 *      通过JUC包下的Lock来实现
 *
 * @Author lfp
 * @Date 2022/7/24
 * @Version 1.0
 */

//第一步 创建资源类，定义属性和操作方法
@Slf4j
class Share {
    private int number = 0;

    //创建Lock 使用可重入所
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    //+1
    @SneakyThrows
    public void incre(){
        //上锁
        lock.lock();

        try {
            //判断
            while (number != 0){
                condition.await();//不满足条件，等待
            }

            //执行操作
            number ++;

            //通知
            condition.signalAll();
            log.info("线程：{}，完成了incre,值为：{}",Thread.currentThread().getName(),number);

        }finally {
            //解锁 在finally块中解锁，防止发生异常出现死锁
            lock.unlock();
        }
    }

    //-1
    @SneakyThrows
    public void decre(){
        //上锁
        lock.lock();

        try {
            //判断
            while (number != 1){
                condition.await();//不满足条件，等待
            }

            //执行操作
            number --;

            //通知
            condition.signalAll();
            log.info("线程：{}，完成了decre,值为：{}",Thread.currentThread().getName(),number);

        }finally {
            //解锁 在finally块中解锁，防止发生异常出现死锁
            lock.unlock();
        }
    }
}


@Slf4j
public class LockIncreaseOrDecrease {
    //第三步 创建多个线程，
    public static void main(String[] args) {
        Share share = new Share();

        //通过内部类的形式，创建线程AA
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    share.incre();//+1
                }
            }
        },"AA").start();

        //通过lambda 表达式的形式，创建线程BB，执行-1 操作
        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                share.decre();//-1
            }
        },"BB").start();

        //创建线程CC，执行+1 操作
        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                share.incre();//+1
            }
        },"CC").start();

        //创建线程DD，执行-1 操作
        new Thread(()->{
            for (int i = 0; i < 5; i++) {
                share.decre();//-1
            }
        },"DD").start();
    }
}
